﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace Master
{
    public class TrafficMarshal
    {
        private InterSection interSection;
        private Dictionary<Car, DirectionData> registeredCars = new Dictionary<Car, DirectionData>();
        private List<Car> movingCars = new List<Car>();

        public TrafficMarshal(InterSection interSection)
        {
            this.interSection = interSection;
        }

        public void registerCar(DirectionData directionData, Car car)
        {
            if (!registeredCars.ContainsKey(car))
                registeredCars.Add(car, directionData);
        }

        public Boolean canMoveForward(Car car)
        {
            if (!registeredCars.ContainsKey(car)) throw new InvalidOperationException(); //unregistered car
            if (movingCars.Contains(car)) return true;
            else return checkIfCarCanMove(car);
        }

        private Boolean checkIfCarCanMove(Car car)
        {
            if ((movingCars.Count == 0 && registeredCars[car].getDirection() != Direction.LEFT) || checkIfPathIsFree(car))
            {
                movingCars.Add(car);
                return true;
            }
            return false;
        }

        private Boolean checkIfPathIsFree(Car car)
        {
            DirectionData directionData = registeredCars[car];
            if (directionData.getDirection() == Direction.LEFT) //car wants to take a left turn
                return (registeredCars.Count == 0 || onlyRegisteredCarsInSameDirection(directionData) || (onlyRegistredCarsGoingLeft(directionData) && movingCars.Count ==0)); //only allowed if no other cars, or only moving cars with same directiondata
            foreach (Car movingCar in movingCars)
            {
                DirectionData movingCarDirectionData = registeredCars[movingCar];
                if (directionData.getOrientation() == movingCarDirectionData.getOrientation()) continue; //moving car is going in same direction --> no collisions possible
                if (!(directionData.getOrientation() == Toolkit.alterOrientationBy(movingCarDirectionData.getOrientation(), 180) //check if this moving car is coming from the opposite direction
                    && movingCarDirectionData.getDirection() != Direction.LEFT)) //check if the moving car does not want to make a left turn either
                    return false;
            }
            return true;
        }

        private Boolean onlyRegisteredCarsInSameDirection(DirectionData directionData)
        {
            //if (movingCars.Count == 0) return false;
            foreach (Car movingCar in registeredCars.Keys)
            {
                DirectionData movingCarDirectionData = registeredCars[movingCar];
                if (movingCarDirectionData.getDirection() != directionData.getDirection() ||
                    movingCarDirectionData.getOrientation() != directionData.getOrientation())
                    return false;
            }
            return true;
        }

        private Boolean onlyRegistredCarsGoingLeft(DirectionData directionData)
        {

            foreach (Car movingCar in registeredCars.Keys)
            {
                DirectionData movingCarDirectionData = registeredCars[movingCar];
                if (movingCarDirectionData.getDirection() != Direction.LEFT)
                    return false;
            }
            return true;
        }

        public void removeCar(Car car)
        {
            registeredCars.Remove(car);
            movingCars.Remove(car);
        }
    }
}

/*
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Windows;

namespace Master
{
    public class TrafficMarshal
    {
        private InterSection interSection;
        private Dictionary<DirectionData, Car> activeTraffic = new Dictionary<DirectionData, Car>();
 

        public TrafficMarshal(InterSection interSection)
        {
            this.interSection = interSection;
        }

        public void registerCar(DirectionData directionData, Car car)
        {
            if (!activeTraffic.Values.Contains(car))
                activeTraffic.Add(directionData, car);
        }

        public Boolean canMoveForward(Car car)
        {
            if (!activeTrafficContainsCar(car)) throw new InvalidOperationException(); //unregistered car
            foreach (KeyValuePair<DirectionData, Car> pair in activeTraffic)
            {
               // Trace.WriteLine(pair.Key.getOrientation().ToString());
             // Trace.WriteLine(pair.Key.getDirection().ToString());
             
                if (pair.Value == car)
                {
                    DirectionData dirData = pair.Key;
                    Direction dir = dirData.getDirection();
                    int orient = dirData.getOrientation();
                   Trace.WriteLine(orient);
                    if (dir == Direction.FORWARD )
                    {
                        return true;
                    }
                    else if (dir == Direction.LEFT)
                    {
                        if (activeTraffic.Count() == 1)
                        {
                            return true;
                        }
                        else if (activeTraffic.Count() > 1)
                        {
                            foreach (Car carLeft in activeTraffic.Values)
                            {
                                Direction dirLeft = carLeft.Direction;
                                int orientLeft = carLeft.Orientation;
                                int orientCheck = alterOrientation(orient, -90);
                                if (orient == orientCheck) { return false; }
                                Trace.WriteLine(orientCheck.ToString());
                            }
                            return false;
                        }
                        else
                        {
                            return false;
                        }
                    }
                    else if (dir == Direction.RIGHT)
                    {
                       return true;
                    }
                }
            }
           return false;
        }
        private int alterOrientation(int orientation, int modifier)
        {
            orientation += modifier;
            if (orientation >= 360)
                orientation -= 360;
            else if (orientation < 0)
                orientation += 360;
            return orientation;
        }
        public void removeCar(Car car)
        {
            foreach (KeyValuePair<DirectionData, Car> carData in activeTraffic) if (carData.Value == car)
            {
                activeTraffic.Remove(carData.Key);
                return;
            }
        }

        private Boolean activeTrafficContainsCar(Car car)
        {
            return activeTraffic.Values.Contains(car);
        }

    }
}
*/